package cn.edu.zzuli.search;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ParallelMultiSearcher;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.wltea.analyzer.lucene.IKQueryParser;

import cn.edu.zzuli.web.Constant;
import cn.edu.zzuli.web.bean.Forum;

public class SearchIndexBean {

	public static String[] FIELDS = { "id", "title", "content" };

	private static IndexSearcher searcher = null;
	private BooleanQuery bq = new BooleanQuery();
	BooleanQuery query = new BooleanQuery();
	BooleanQuery rbq = new BooleanQuery();
	private Analyzer analyzer = new IKAnalyzer();
	private ParallelMultiSearcher mSearcher = null;
	private Sort sf = null;
	private SearchResultBean bean = new SearchResultBean();

	public SearchIndexBean(String indexpath) {
		try {
			// if(searcher==null){
			File file = new File(indexpath);
			searcher = new IndexSearcher(FSDirectory.open(file));
			mSearcher = new ParallelMultiSearcher(searcher);
			// }

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 在多个字段搜索
	 * 
	 * @param keyword
	 *            搜索关键字
	 * @return BooleanQuery
	 */
	public BooleanQuery setMultiField(String keyword) {
		try {
			Query query = IKQueryParser.parseMultiField(FIELDS, keyword);
			bq.add(query, BooleanClause.Occur.MUST);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bq;
	}

	/**
	 * 在多个字段搜索
	 * 
	 * @param keyword
	 *            搜索关键字
	 * @param filedmap
	 *            列的权重值
	 * @return BooleanQuery
	 */
	public BooleanQuery setMultiField(String keyword,
			Map<String, Float> filedmap) {
		try {
			bq.add(query, BooleanClause.Occur.MUST);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bq;
	}

	/**
	 * 在多个字段搜索
	 * 
	 * @param keyword
	 *            搜索关键字
	 * @return BooleanQuery
	 */
	public BooleanQuery setMultiFieldSHOULD(String keyword) {

		try {
			Query query = IKQueryParser.parseMultiField(FIELDS, keyword);
			bq.add(query, BooleanClause.Occur.SHOULD);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return bq;
	}

	/**
	 * 在单个字段中搜索(前缀)
	 * 
	 * @param field
	 *            字段关键字
	 * @param keyword
	 *            搜索关键字
	 * @return BooleanQuery 说明 此方法为了以后使用
	 */
	public BooleanQuery setSinglePrefix(String field, String keyword) {
		try {
			// Term prefix = new Term("I_VCPID","63010101");
			Term prefix = new Term(field, keyword);
			PrefixQuery query = new PrefixQuery(prefix);
			bq.add(query, BooleanClause.Occur.MUST);
			return bq;
		} catch (Exception e) {
			e.printStackTrace();
			return bq;
		}
	}

	/**
	 * 在单个字段中搜索
	 * 
	 * @param field
	 *            字段关键字
	 * @param keyword
	 *            搜索关键字
	 * @return BooleanQuery
	 */
	public BooleanQuery setSingleField(String field, String keyword) {
		try {
			bq.add(getQuery(field, keyword), BooleanClause.Occur.MUST);
			return bq;
		} catch (ParseException e) {
			e.printStackTrace();
			return bq;
		}
	}

	public BooleanQuery SetShould(String field, String keyword) {

		Term prefix1 = new Term(field, keyword);
		TermQuery tq = new TermQuery(prefix1);
		query.add(tq, BooleanClause.Occur.SHOULD);
		return query;
	}

	/**
	 * SearchBean集合
	 * 
	 * @return
	 */
	public List<Forum> getCustomers() {

		List<Forum> list = bean.setCustomers(mSearcher, getSearchHits());
		return list;
	}

	/**
	 * SearchPBean排序后集合
	 * 
	 * @return
	 */
	public List<Forum> getCustomersSort() {
		List<Forum> list = bean
				.setCustomers(mSearcher, getSearchSortHits());
		return list;
	}

	/**
	 * 根据指定字段排序
	 * 
	 * @param field
	 *            搜索的字段
	 * @param sort
	 *            true 降序 false 升序
	 * @param state
	 *            field 值类型 0 整型 1 字符型 （最好是整型）
	 * @return Sort
	 */
	public Sort setSort(String field, boolean sort, int state) {
		if (state == 0) {
			sf = new Sort(new SortField(field, SortField.INT, sort));
		} else {
			sf = new Sort(new SortField(field, SortField.STRING, sort));
		}

		return sf;
	}

	/**
	 * 得到搜索结果集
	 * 
	 * @return Hits
	 */
	private TopDocs getSearchSortHits() {
		try {
			return mSearcher.search(bq, null,
					mSearcher.search(bq, 1).totalHits, sf);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 得到查重后的结果集
	 * 
	 * @return Hits
	 */
	@SuppressWarnings("unused")
	private TopDocs getReSearchHits() {
		try {
			if (!query.toString().equals("")) {
				bq.add(query, BooleanClause.Occur.MUST);
			}
			return mSearcher.search(query, mSearcher.search(rbq, 1).totalHits);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 得到搜索结果集
	 * 
	 * @return Hits
	 */
	private TopDocs getSearchHits() {
		try {
			// 临时加上
			Term prefix1 = new Term("id", "b00004");
			TermQuery tq = new TermQuery(prefix1);
			bq.add(tq, BooleanClause.Occur.MUST_NOT);
			rbq.add(bq, BooleanClause.Occur.MUST);
			if (!query.toString().equals("")) {
				rbq.add(query, BooleanClause.Occur.MUST);
			}

			return mSearcher.search(rbq, mSearcher.search(rbq, 1).totalHits);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 得到搜索结果集
	 * 
	 * @return Hits
	 */
	@SuppressWarnings("unused")
	private TopDocs getSearchPHits() {
		try {
			rbq.add(bq, BooleanClause.Occur.MUST);
			if (!query.toString().equals("")) {
				rbq.add(query, BooleanClause.Occur.MUST);
			}
			return mSearcher.search(rbq, mSearcher.search(rbq, 1).totalHits);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 得到搜索结果集
	 * 
	 * @return Hits
	 */
	@SuppressWarnings("unused")
	private TopDocs getSearchPSortHits() {
		try {
			if (!bq.toString().equals("")) {
				rbq.add(bq, BooleanClause.Occur.MUST);
			}
			if (!query.toString().equals("")) {
				rbq.add(query, BooleanClause.Occur.MUST);
			}
			return mSearcher.search(rbq, null,
					mSearcher.search(rbq, 1).totalHits, sf);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 以下应用享元模式处理多个，单个字段之间并集搜索
	 */
	private static HashMap<String, Query> queryMap = new HashMap<String, Query>();
	private static HashMap<String, QueryParser> queryParserMap = new HashMap<String, QueryParser>();

	private Query getQuery(String field, String keyword) throws ParseException {
		if (queryMap.containsKey(field + keyword)) {
			return (Query) queryMap.get(field + keyword);
		} else {
			QueryParser qp = getQueryParser(field);
			Query query = qp.parse(keyword);
			// queryMap.put(keyword, query);
			queryMap.put(field + keyword, query);
			return query;
		}
	}

	private QueryParser getQueryParser(String field) {
		if (queryParserMap.containsKey(field)) {
			return queryParserMap.get(field);
		} else {
			// Query query = IKQueryParser.parse(field, query)
			QueryParser queryParser = new QueryParser(Version.LUCENE_30, field,
					analyzer);
			return queryParser;
		}
	}

	public static void main(String args[]) {
		SearchIndexBean t = new SearchIndexBean(Constant.SEARCH_INDEX_DIR);
		t.setMultiField("飞飞");
		t.setSort("id", true, 1);// 默认设置搜索结果按时间降序排序 测试使用
		List<Forum> list = t.getCustomersSort();// t.getCustomers();
		System.out.println("list--" + list.size());
		for (int i = 0; i < list.size(); i++) {
			try {
				Forum customers = (Forum) list.get(i);
				System.out.println(customers.getId() + "  "
						+ customers.getTitle() + "[[[["
						+ customers.getContent());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
